package com.stottlerhenke.simbionic.editor;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.stottlerhenke.simbionic.api.SB_VarType;
import com.stottlerhenke.simbionic.editor.gui.ComponentRegistry;
import com.stottlerhenke.simbionic.editor.gui.SB_Catalog;
import com.stottlerhenke.simbionic.editor.gui.SB_ProjectBar;
import com.stottlerhenke.simbionic.engine.core.SB_Method;
import com.stottlerhenke.simbionic.engine.core.SB_ParamList;

public class FileManager
{
	private SimBionicEditor mEditorApp = null;
	private static FileManager mInstance = null;
	protected enum DIRECTION {IN_DIR, OUT_DIR, IN_OUT_DIR};
	
	private File mSBPFile = null;
	private File mAPDFile = null;
	private File mSimFile = null;
	private File mXMLFile = null;
	private File mHeaderFile = null;
	private File mJavaFile = null;
	
	/**
	 *  
	 */
	private FileManager(SimBionicEditor pEditorApp)
	{
		super();
		if(pEditorApp == null) throw new RuntimeException("SimBionic app cannot be null for FileManager!");
		mEditorApp = pEditorApp;
	}

	public static FileManager initialize(SimBionicEditor pEditorApp)
	{
		mInstance = new FileManager(pEditorApp);
		return mInstance;
	}
	
	public static FileManager getInstance()
	{
		if(mInstance != null) return mInstance;
		else throw new RuntimeException("FileManager not initialized!");
	}
	
	public String getProjectFileName()
	{
		if(mSBPFile == null) return new String();
		String name = mSBPFile.getName();
		int index = name.lastIndexOf('.');
		return name.substring(index);
	}
	
  public int getRevisionNumber(File pSimFile)
	{
		if (pSimFile != null && pSimFile.exists())
		{
			try
			{
				BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(pSimFile)));
				String line = in.readLine();
				line = in.readLine();
				in.close();
				return Integer.parseInt(line.substring(13));
			}
			catch (FileNotFoundException exception)
			{
				System.err.println("file not found");
			}
			catch (IOException exception)
			{
				System.err.println("i/o exception");
			}
		}
		return 0;
	}
  
  	private String getExt(File f)
  	{
  		int idx = f.getName().indexOf(".");
  		if (idx < 0 || idx == (f.getName().length()-1))
  			return null;
  		
  		return f.getName().substring(idx+1);
  	}

	
	protected void exportHeader()
	{
		SB_ProjectBar pbar = mEditorApp.getProjectBar();
		boolean exportConstants = false;	// for now
		
		File fileH = null;
		File fileCPP = null;
		String pfname = getProjectFileName();
		fileH = new File(pfname + "_Interface.h");
		fileCPP = new File(pfname + "_Interface.cpp");
		
		//getFileChooserH().setSelectedFile(fileH);
		//getFileChooserH().setDialogTitle("Export C++ Header");
		//int returnVal = getFileChooserH().showDialog(ComponentRegistry.getFrame(), "Export");
		
		JFileChooser fc = getFileChooserDir();
		int returnVal = fc.showDialog(ComponentRegistry.getFrame(), "Export");
		if (returnVal == JFileChooser.APPROVE_OPTION)
		{
			fileH = fc.getSelectedFile();
			String ext = getExt(fileH);
			if (ext == null)
			{
				String path = fileH.getPath();
				fileH = new File(path + ".h");
				fileCPP = new File(path + ".cpp");
			}
			else
			{
				String base = fileH.getAbsolutePath();
				int idx = base.lastIndexOf(".");
				if (idx > 0)
					base = base.substring(0, idx);
				fileCPP = new File(base + ".cpp");
			}
			if (fileH.exists() || fileCPP.exists())
			{
				int n = JOptionPane.showConfirmDialog(ComponentRegistry.getFrame(), "'"
											+ fileH.getPath() + "' already exists. \n"
											+ "Do you want to replace it?", "Export C++ Header",
											JOptionPane.YES_NO_OPTION);
				if (n == JOptionPane.NO_OPTION)
					return;
			}
			
			
			try
			{
				// open header file for writing
				BufferedWriter outH = new BufferedWriter(new OutputStreamWriter(
						new FileOutputStream(fileH)));
				BufferedWriter outCPP = new BufferedWriter(new OutputStreamWriter(
						new FileOutputStream(fileCPP)));
	
				// write comment line
				String filename = fileH.getName();
				String name = filename;
				int len = name.length();
				if (len > 10 && name.endsWith("_Interface"))
					name = name.substring(0, len-10);
				name = name.replace('-', '_');
				name = name.replace(' ', '_');
				name = name.substring(0, name.length() - 2);
				String nameCAPS = name.toUpperCase(); 
				
				
				outH.write("// " + name + ".h : behavior editor generated header file");
				outH.newLine();
				outH.newLine();
				outCPP.write("// " + name + ".cpp : behavior editor generated implementation file");
				outCPP.newLine();
				outCPP.newLine();
				
				
				if (exportConstants)
				{
					//if (strConstsPathName.IsEmpty() || strConstsPathName.CompareNoCase(strPathNameH) == 0)
					//	strConstsPathName = ExtractPath(strPathNameH) + "\\" + strName + "_constants.h";
					//outH.write("#include \"" + /*ExtractFileName(strConstsPathName) +*/ ".h");
					outH.write("#include \"" + name + "_constants.h\"");
					outH.newLine();
				}
				
				outH.write("#include <Interface\\AI_Interface.h>");
				outH.newLine();
				outH.newLine();
				outCPP.write("#include \"" + name + ".h\"");
				outCPP.newLine();
				outCPP.newLine();
				
				// SIM revision number
				int rev = getRevisionNumber(mSimFile);
				if (rev == 0) rev = 1;
				outH.write("// sim revision number");
				outH.newLine();
				outH.write("#define SIM_REV " + rev);
				outH.newLine();
				outH.newLine();
				
				// ACTIONS
				outH.write("// actions");
				outH.newLine();
				
				DefaultMutableTreeNode actions = pbar.getCatalog()._actions;
	            actions = pbar.deepCopyWithStrip("Core", actions, actions);
	            
	            int actionCount = 0;
	            Enumeration en = actions.breadthFirstEnumeration();
	            while(en.hasMoreElements())
	            {
	            	DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	            	Object oaction = tnode.getUserObject();
	            	if (oaction instanceof SB_Action)
	            	{
	            		SB_Action action = (SB_Action)oaction;
	            		outH.write("#define " + nameCAPS + "_ACTION_" + action.getName() + " " + action.getId());
	            		outH.newLine();
	            		actionCount++;
	            	}
	            }
	            outH.newLine();
	            
	            // PREDICATES
	            
				outH.write("// predicates");
				outH.newLine();
				
				DefaultMutableTreeNode predicates = pbar.getCatalog()._predicates;
	            predicates = pbar.deepCopyWithStrip("Core", predicates, predicates);
	            
	            int predicateCount = 0;
	            en = predicates.breadthFirstEnumeration();
	            while(en.hasMoreElements())
	            {
	            	DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	            	Object opredicate = tnode.getUserObject();
	            	if (opredicate instanceof SB_Predicate)
	            	{
	            		// write line in the form "#define PROJECT_PRED_name id"
	            		SB_Predicate predicate = (SB_Predicate)opredicate;
	            		outH.write("#define " + nameCAPS + "_PRED_" + predicate.getName() + " " + predicate.getId());
	            		outH.newLine();
	            		predicateCount++;
	            	}
	            }
	            
	            
	            
	            if (exportConstants)
	            {
	            	// TODO: not supported
	            	exportCPPConstants("", actions, predicates, false, false, false, "");
	            }
	            else
	            {
	            	includeCPPConstants(outH, name, actions, predicates, false, true);
	            }
	            
	            outH.newLine();
	            
	            outH.write("class " + name + " : public AI_Interface");
	            outH.newLine();
	            outH.write("{");
	            outH.newLine();
	            outH.write("public:");
	            outH.newLine();
	            outH.write("\tAI_String GetModuleName();");
	            outH.newLine();
	            outH.write("\tFuncSpecVec* GetModuleActions();");
	            outH.newLine();
	            outH.write("\tFuncSpecVec* GetModulePredicates();");
	            outH.newLine();
	            outH.write("\tAI_String GetActionName(int actionId);");
	            outH.newLine();
	            outH.write("\tAI_String GetPredicateName(int predId);");
	            outH.newLine();
	            outH.newLine();
	            outH.write("\tvoid DoAction(AI_ProcId actionId, AI_Entity entityId, AI_ParamVec& params);");
	            outH.newLine();
	            
	            outCPP.write("AI_String " + name + "::GetModuleName()");
	            outCPP.newLine();
	            outCPP.write("{");
	            outCPP.newLine();
	            outCPP.write("\treturn \"" + name + "\";");
	            outCPP.newLine();
	            outCPP.write("}");
	            outCPP.newLine();
	            outCPP.newLine();
	            
	            outCPP.write("FuncSpecVec* " + name + "::GetModuleActions()");
	            outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tFuncSpecVec* actions = new FuncSpecVec();");
	        	outCPP.newLine();
	        	outCPP.write("\tactions->reserve(" + actionCount + ");");
	        	outCPP.newLine();
	        	outCPP.newLine();
	        	outCPP.write("\tAI_FuncSpec *fs;");
	        	outCPP.newLine();
	        	outCPP.write("\tFuncParamSpec *fps;");
	        	outCPP.newLine();
	           
	        	en = actions.breadthFirstEnumeration();
	            while(en.hasMoreElements())
	            {
	            	DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	            	Object oaction = tnode.getUserObject();
	            	if (oaction instanceof SB_Action)
	            	{
	            		SB_Action action = (SB_Action)oaction;
	            		outCPP.write("\t// " + action);	// was action.getFullName()	
	            		outCPP.newLine();
	            		outCPP.write("\tfs = new AI_FuncSpec();");
	            		outCPP.newLine();
	            		outCPP.write("\tfs->name = \"" + action.getName() + "\";");
	            		outCPP.newLine();
	            		outCPP.write("\tfs->id = " + action.getId() + ";");
	            		outCPP.newLine();
	            		//outCPP.write("\tfs->type = " << GetCppTypeConstant(action->GetType()) << ";");
	            		outCPP.write("\tfs->type = kVoid;");
	            		outCPP.newLine();
	            		
	            		Enumeration params = tnode.children();
	            		outCPP.write("\tfs->params.reserve(" + tnode.getChildCount() + ");");
	            		outCPP.newLine();
	            		while(params.hasMoreElements())
	            		{
	            			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
	            			Object userObj = paramNode.getUserObject();
	            			if (userObj instanceof SB_Parameter)
	            			{
	            				SB_Parameter param = (SB_Parameter)userObj;
	            				//SB_VarType vtype = SB_VarType.getTypeFromInt(param.getType());
	            				outCPP.write("\tfps = new FuncParamSpec(\"" + param.getName() + "\", " +
	            						getDirectionConstant(param.getDirection()) + ", " +
	            						getCppTypeConstant(param.getType()) + ");");
	            				outCPP.newLine();
	            				outCPP.write("\t(fs->params).push_back(fps);");
	            				outCPP.newLine();
	            			}
	            		}
	            		outCPP.write("\tactions->push_back(fs);");
	            		outCPP.newLine();
	            		outCPP.newLine();
	            	}
	            }
	            
	            if (name.equals("Core"))
	            {
	            	outCPP.newLine();
	        		outCPP.write("\t// None");
	        		outCPP.newLine();
	        		outCPP.write("\tfs = new AI_FuncSpec();");
	        		outCPP.newLine();
	        		outCPP.write("\tfs->name = \"None\";");
	        		outCPP.newLine();
	        		outCPP.write("\tfs->id = -1;");
	        		outCPP.newLine();
	        		outCPP.write("\tfs->type = kNoSuchName;");
	        		outCPP.newLine();
	        		outCPP.write("\tactions->push_back(fs);");
	        		outCPP.newLine();
	        		outCPP.newLine();
	            }
	            
	            outCPP.write("\treturn actions;");
	            outCPP.newLine();
	        	outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();

	        	outCPP.write("FuncSpecVec* " + name + "::GetModulePredicates()");
	        	outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tFuncSpecVec* preds = new FuncSpecVec();");
	        	outCPP.newLine();
	        	outCPP.write("\tpreds->reserve(" + predicateCount + ");");
	        	outCPP.newLine();
	        	outCPP.newLine();
	        	outCPP.write("\tAI_FuncSpec *fs;");
	        	outCPP.newLine();
	        	outCPP.write("\tFuncParamSpec *fps;");
	        	outCPP.newLine();
	        	
	        	en = predicates.breadthFirstEnumeration();
	            while(en.hasMoreElements())
	            {
	            	DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	            	Object opred = tnode.getUserObject();
	            	if (opred instanceof SB_Predicate)
	            	{
	            		SB_Predicate predicate = (SB_Predicate)opred;
	            		outCPP.write("\t// " + predicate); //predicate.getName() + " : " + predicate.getRetTypeName());	// was predicate.getFullName()	
	            		outCPP.newLine();
	            		outCPP.write("\tfs = new AI_FuncSpec();");
	            		outCPP.newLine();
	            		outCPP.write("\tfs->name = \"" + predicate.getName() + "\";");
	            		outCPP.newLine();
	            		outCPP.write("\tfs->id = " + predicate.getId() + ";");
	            		outCPP.newLine();
	            		//outCPP.write("\tfs->type = " << GetCppTypeConstant(action->GetType()) << ";");
	            		//SB_VarType vtype = new SB_VarType(predicate.getRetType());
	            		outCPP.write("\tfs->type = " + getCppTypeConstant(predicate.getRetType()) + ";");
	            		outCPP.newLine();
	            		
	            		Enumeration params = tnode.children();
	            		outCPP.write("\tfs->params.reserve(" + tnode.getChildCount() + ");");
	            		outCPP.newLine();
	            		while(params.hasMoreElements())
	            		{
	            			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
	            			Object userObj = paramNode.getUserObject();
	            			if (userObj instanceof SB_Parameter)
	            			{
	            				SB_Parameter param = (SB_Parameter)userObj;
	            				//vtype = new SB_VarType(param.getType());
	            				outCPP.write("\tfps = new FuncParamSpec(\"" + param.getName() + "\", " +
	            						getDirectionConstant(param.getDirection()) + ", " +
	            						getCppTypeConstant(param.getType()) + ");");
	            				outCPP.newLine();
	            				outCPP.write("\t(fs->params).push_back(fps);");
	            				outCPP.newLine();
	            			}
	            		}
	            		outCPP.write("\tpreds->push_back(fs);");
	            		outCPP.newLine();
	            		outCPP.newLine();
	            	}
	            }
	            
	            outCPP.write("\treturn preds;");
	            outCPP.newLine();
	            outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();
	        	
	        	outCPP.write("AI_String " + name + "::GetActionName(int actionId)");
	        	outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tswitch (actionId)");
	        	outCPP.newLine();
	        	outCPP.write("\t{");
	        	outCPP.newLine();
	        	
	        	en = actions.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Action)
	        		{
	        			SB_Action action = (SB_Action)userObj;
	        			outCPP.write("\tcase " + nameCAPS + "_ACTION_" + action.getName() + ":");
	        			outCPP.newLine();
	        			outCPP.write("\t\treturn \"" + action.getName() + "\";");
	        			outCPP.newLine();
	        		}
	        	}
	        	
	        	outCPP.write("\tdefault:");
	        	outCPP.newLine();
	        	outCPP.write("\t\t// unknown action");
	        	outCPP.newLine();
	        	outCPP.write("\t\treturn \"\";");
	        	outCPP.newLine();

	        	outCPP.write("\t}");
	        	outCPP.newLine();
	        	outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();

	        	outCPP.write("AI_String " + name + "::GetPredicateName(int predId)");
	        	outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tswitch (predId)");
	        	outCPP.newLine();
	        	outCPP.write("\t{");
	        	outCPP.newLine();
	        	
	        	en = predicates.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Predicate)
	        		{
	        			SB_Predicate predicate = (SB_Predicate)userObj;
	        			outCPP.write("\tcase " + nameCAPS + "_PRED_" + predicate.getName() + ":");
	        			outCPP.newLine();
	        			outCPP.write("\t\treturn \"" + predicate.getName() + "\";");
	        			outCPP.newLine();
	        		}
	        	}
	        	
	        	outCPP.write("\tdefault:");
	        	outCPP.newLine();
	        	outCPP.write("\t\t// unknown predicate");
	        	outCPP.newLine();
	        	outCPP.write("\t\treturn \"\";");
	        	outCPP.newLine();

	        	outCPP.write("\t}");
	        	outCPP.newLine();
	        	outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();
	        	
	        	outCPP.write("void " + name + "::DoAction(AI_ProcId actionId, AI_Entity entityId, AI_ParamVec& params)");
	        	outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tswitch (actionId)");
	        	outCPP.newLine();
	        	outCPP.write("\t{");
	        	outCPP.newLine();
	        	
	        	en = actions.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Action)
	        		{
	        			SB_Action action = (SB_Action)userObj;
	        			outCPP.write("\tcase " + nameCAPS + "_ACTION_" + action.getName() + ":");
	        			outCPP.newLine();
	        			exportCPPFuncCall(outCPP, action, tnode);
	        		}
	        	}
	        	
	        	outCPP.write("\tdefault:");
	        	outCPP.newLine();
	        	outCPP.write("\t\t// unknown action");
	        	outCPP.newLine();
	        	outCPP.write("\t\tbreak;");
	        	outCPP.newLine();

	        	outCPP.write("\t}");
	        	outCPP.newLine();
	        	outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();

	        	outH.write("\tAI_Param DoPredicate(AI_ProcId predId, AI_Entity entityId, AI_ParamVec& params);");
	        	outH.newLine();
	        	outH.newLine();
	        	outCPP.write("AI_Param " + name + "::DoPredicate(AI_ProcId predId, AI_Entity entityId, AI_ParamVec& params)");
	        	outCPP.newLine();
	        	outCPP.write("{");
	        	outCPP.newLine();
	        	outCPP.write("\tswitch (predId)");
	        	outCPP.newLine();
	        	outCPP.write("\t{");
	        	outCPP.newLine();
	        	
	        	en = predicates.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Predicate)
	        		{
	        			SB_Predicate predicate = (SB_Predicate)userObj;
	        			outCPP.write("\tcase " + nameCAPS + "_PRED_" + predicate.getName() + ":");
	        			outCPP.newLine();
	        			exportCPPFuncCall(outCPP, predicate, tnode);
	        		}
	        	}
	        	
	        	outCPP.write("\tdefault:");
	        	outCPP.newLine();
	        	outCPP.write("\t\t// unknown predicate");
	        	outCPP.newLine();
	        	outCPP.write("\t\treturn AI_Param();");
	        	outCPP.newLine();

	        	outCPP.write("\t}");
	        	outCPP.newLine();
	        	outCPP.write("}");
	        	outCPP.newLine();
	        	outCPP.newLine();
	        	
	        	// Action implementations
	        	outH.write("\t// actions");
	        	outH.newLine();
	        	outCPP.write("// ---- Action Implementations");
	        	outCPP.newLine();
	        	
	        	en = actions.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Action)
	        		{
	        			SB_Action action = (SB_Action)userObj;
	        			exportCPPFuncDecl(outH, action, tnode);
	        			exportCPPFuncImpl(outCPP, name, action, tnode);
	        		}
	        	}
	        	
	        	outH.newLine();
	        	outCPP.newLine();
	        	
	        	// Predicate implementations
	        	outH.write("\t// predicates");
	        	outH.newLine();
	        	outCPP.write("// ---- Predicate Implementations");
	        	outCPP.newLine();
	        	
	        	en = predicates.breadthFirstEnumeration();
	        	while(en.hasMoreElements())
	        	{
	        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
	        		Object userObj = tnode.getUserObject();
	        		if (userObj instanceof SB_Predicate)
	        		{
	        			SB_Predicate predicate = (SB_Predicate)userObj;
	        			exportCPPFuncDecl(outH, predicate, tnode);
	        			exportCPPFuncImpl(outCPP, name, predicate, tnode);
	        		}
	        	}
	        	
	        	outH.write("};");
	        	outH.newLine();
	
	//			// export actions, predicates
				//_catalog.exportHeader(out, name);
	
				outH.close();
				outCPP.close();
				
				// TODO: maybe add open after export here?
				// ::WinExec("notepad.exe " + strPathNameH, SW_SHOW);
			}
			catch (IOException exception)
			{
				System.err.println("i/o exception");
				JOptionPane
						.showMessageDialog(ComponentRegistry.getFrame(), "There was an error writing to the file: "
								+ exception.getMessage(), "File error",
								JOptionPane.ERROR_MESSAGE);
			}
			
		}
	//	File fileH = null;
	//	if (_fileSBP != null)
	//	{
	//		String name = _fileSBP.getName();
	//		name = name.substring(0, name.length() - 4);
	//		fileH = new File(_fileSBP.getParent() + /* File.separator */"//" + name
	//				+ ".h");
	//	}
	//	getFileChooserH().setSelectedFile(fileH);
	//	getFileChooserH().setDialogTitle("Export C++ Header");
	//	int returnVal = getFileChooserH().showDialog(ComponentRegistry.getFrame(),
	//			"Export");
	//	if (returnVal == JFileChooser.APPROVE_OPTION)
	//	{
	//		fileH = getFileChooserH().getSelectedFile();
	//		String ext = getExt(fileH);
	//		if (ext == null) fileH = new File(fileH.getPath() + ".h");
	//		if (fileH.exists())
	//		{
	//			int n = JOptionPane.showConfirmDialog(ComponentRegistry.getFrame(), "'"
	//					+ fileH.getPath() + "' already exists. \n"
	//					+ "Do you want to replace it?", "Export C++ Header",
	//					JOptionPane.YES_NO_OPTION);
	//			if (n == JOptionPane.NO_OPTION) return;
	//		}
	//
	//		try
	//		{
	//			// open header file for writing
	//			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
	//					new FileOutputStream(fileH)));
	//
	//			// write comment line
	//			String name = fileH.getName();
	//			out.write("// " + name + " : SimBionic generated constants");
	//			out.newLine();
	//			out.newLine();
	//			name = name.substring(0, name.length() - 2).toUpperCase();
	//			// SIM revision number
	//			int rev = getRevisionNumber(_fileSIM);
	//			if (rev == 0) rev = 1;
	//			out.write("// sim revision number");
	//			out.newLine();
	//			out.write("#define SIM_REV " + rev);
	//			out.newLine();
	//			out.newLine();
	//
	//			// export actions, predicates
	//			_catalog.exportHeader(out, name);
	//
	//			out.close();
	//		}
	//		catch (IOException exception)
	//		{
	//			System.err.println("i/o exception");
	//			JOptionPane
	//					.showMessageDialog(this, "There was an error writing to the file: "
	//							+ exception.getMessage(), "File error",
	//							JOptionPane.ERROR_MESSAGE);
	//		}
	//	}
	}
	
	protected String getDirectionConstant(int direction)
	{
		DIRECTION dir = DIRECTION.values()[direction];
		switch(dir)
		{
			case IN_DIR:
				return "kIn";
			case OUT_DIR:
				return "kOut";
			case IN_OUT_DIR:
				return "kInOut";
			default:
				return "kNone";
		}
	}
	
	protected String getCppTypeConstant(int typeCode)
	{
		//SB_ProjectBar pbar = mEditorApp.getProjectBar();
		
		// this function is unimplemented
		//return pbar.getTypeManager().getCppTypeConstant(type);
		
		//SB_TypeManager typeManager = ComponentRegistry.getProjectBar().getTypeManager();
    	SB_VarType newType = SB_TypeManager.convertOldTypeId(typeCode);
    	//return typeManager.getTypeName(newType);
    	
		switch(newType.getState())
		{
			 case -1: return "kInvalid";
		      case 0: return "kFloat";
		      case 1: return "kString";
		      case 2: return "kEntity";
		      case 3: return "kVector";
		      case 4: return "kData";
		      case 5: return "kAny";
		      case 6: return "kInteger";
		      case 7: return "kBoolean";
		      case 8: return "kArray";
		      case 9: return "kTable";
		      case 10: return "kLAST_VARTYPE"; 
		}
		
		return "kUnknown";
		
	}
	
	protected void exportCPPFuncCall(BufferedWriter out, SB_Function func, DefaultMutableTreeNode funcRoot)
		throws IOException
	{
		int retType = SB_VarType.kVoid.getState();
		String retTypeName = "kVoid";
		if (func instanceof SB_Predicate)
		{
			SB_Predicate pred = (SB_Predicate)func;
			retType = pred.getRetType();
			retTypeName = pred.getRetTypeName();
		}
		
		boolean hasStringRef = false;
		Enumeration params = funcRoot.children();
		int size = funcRoot.getChildCount();
		int i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				if (SB_VarType.getTypeFromInt(param.getType()) == SB_VarType.kString &&
						param.getDirection() != DIRECTION.IN_DIR.ordinal())
				{
					if (!hasStringRef)
					{
						hasStringRef = true;
						out.write("\t\t{");
						out.newLine();
					}
					out.write("\t\t\tstd::string param" + i + "( params[" + i + "].String() );");
					out.newLine();
				}
				i++;
			}
		}
		
		out.write("\t\t");
		if (hasStringRef)
			out.write("\t");
		
		if (retType != SB_VarType.kVoid.getState())
		{
			if (hasStringRef)
				out.write("AI_Param retVal = ");
			else
				out.write("return ");
		}
		
		out.write(func.getName() + "(");
		params = funcRoot.children();
		i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				if (SB_VarType.getTypeFromInt(param.getType()) == SB_VarType.kString &&
						param.getDirection() != DIRECTION.IN_DIR.ordinal())
				{
					out.write("param" + i);
				}
				else
				{
					//String typeFunc =  Character.toUpperCase(param.getTypeName().charAt(0)) + param.getTypeName().substring(1);
					out.write("params[" + i + "]" + getCPPTypeName(param, false));              //." + typeFunc + "()");
				}
				if (i < (size-1))
					out.write(", ");
				i++;
			}
		}
		
		out.write(");");
		out.newLine();
		
		params = funcRoot.children();
		i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				if (SB_VarType.getTypeFromInt(param.getType()) == SB_VarType.kString &&
						param.getDirection() != DIRECTION.IN_DIR.ordinal())
				{
					out.write("\t\t\tparams[" + i + "].SetString( param" + i + ".c_str() );");
					out.newLine();
				}
				i++;
			}
		}
		
		if (retType != SB_VarType.kVoid.getState() && hasStringRef)
		{
			out.write("\t\t\treturn retVal;");
			out.newLine();
		}
		
		if (hasStringRef)
		{
			out.write("\t\t}");
			out.newLine();
		}
		
		if (retType == SB_VarType.kVoid.getState())
		{
			out.write("\t\tbreak;");
			out.newLine();
		}
		
	}
	
	protected void exportCPPFuncDecl(BufferedWriter out, SB_Function func, DefaultMutableTreeNode funcRoot)
			throws IOException
	{
		int retType = SB_VarType.kVoid.getState();
		String retTypeName = "kVoid";
		if (func instanceof SB_Predicate)
		{
			SB_Predicate pred = (SB_Predicate)func;
			retType = pred.getRetType();
			retTypeName = pred.getRetTypeName();
		}
		
		out.write("\t");
		if (retType != SB_VarType.kVoid.getState())
			out.write("AI_Param ");
		else
			out.write("void ");
		out.write(func.getName() + "(");
		Enumeration params = funcRoot.children();
		int size = funcRoot.getChildCount();
		int i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				
				//String aiName = FileManager.convertTypeToSBType(param.getType());
				out.write(getCPPTypeName(param, true) + " " + param.getName());
				if (i < (size-1))
					out.write(", ");
				
				i++;
			}
		}
		out.write(");");
		out.newLine();
	}
	
	protected void exportCPPFuncImpl(BufferedWriter out, String name, SB_Function func, DefaultMutableTreeNode funcRoot)
			throws IOException
	{
		int retType = SB_VarType.kVoid.getState();
		String retTypeName = "kVoid";
		if (func instanceof SB_Predicate)
		{
			SB_Predicate pred = (SB_Predicate)func;
			retType = pred.getRetType();
			retTypeName = pred.getRetTypeName();
		}
		
		out.write("/**");
		out.newLine();
		
		String descript = func.getDescription();
		if (!descript.isEmpty())
		{
			String[] array = wrapText(descript, 65);
			
			for(String line : array)
			{
				out.write(" * " + line);
				out.newLine();
			}
		}
		
		String funcName = func.getName();
		Enumeration params = funcRoot.children();
		int size = funcRoot.getChildCount();
		int i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				
				out.write(" * @param " + param);// param.getName() + " : " + param.getTypeName());
				out.newLine();
				i++;
			}
		}
		
		if (retType != SB_VarType.kVoid.getState())
		{
			out.write(" * @return " + retTypeName);
			out.newLine();
		}
		out.write(" */");
		out.newLine();
		
		if (retType != SB_VarType.kVoid.getState())
			out.write("AI_Param ");
		else
			out.write("void ");
		out.write(name + "::" + funcName + "(");
		
		params = funcRoot.children();
		i = 0;
		while(params.hasMoreElements())
		{
			DefaultMutableTreeNode paramNode = (DefaultMutableTreeNode)params.nextElement();
			Object userObj = paramNode.getUserObject();
			if (userObj instanceof SB_Parameter)
			{
				SB_Parameter param = (SB_Parameter)userObj;
				
				//String aiName = FileManager.convertTypeToSBType(param.getType());
				out.write(getCPPTypeName(param, true) + " " + param.getName());
				if (i < (size-1))
					out.write(", ");
				i++;
			}
		}
		
		out.write(")");
		out.newLine();
		
		out.write("{");
		out.newLine();
		
		out.write("\t// your " + funcName + " implementation here");
		out.newLine();
		if (retType != SB_VarType.kVoid.getState())
		{
			out.write("\treturn AI_Param(); // TODO: your return value here");
			out.newLine();
		}
		
		out.write("}");
		out.newLine();
	}
	
	protected void includeCPPConstants(BufferedWriter out, String name,
			DefaultMutableTreeNode actions, DefaultMutableTreeNode predicates,
			boolean paConstants, boolean userDefined) throws IOException
	{
		String nameCAPS = name.toUpperCase();
		
		/*	
		// SIM revision number
		SB_ProjectBar pbar = mEditorApp.getProjectBar();
		int rev = pbar.getRevisionNumber();
		if (rev == 0)
			rev = 1;
		out.write("// sim revision number");
		out.newLine();
		out.write("#define SIM_REV " + rev);
		out.newLine();
		out.newLine();
		 */
		
		if (paConstants)
		{
			assert(actions != null && predicates != null);
			
			Enumeration en = actions.breadthFirstEnumeration();
        	while(en.hasMoreElements())
        	{
        		// write line of the form "#define PROJECT_ACTION_name id"
        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
        		Object userObj = tnode.getUserObject();
        		if (userObj instanceof SB_Action)
        		{
        			SB_Action action = (SB_Action)userObj;
        			out.write("#define " + nameCAPS + "_ACTION_" + action.getName() + " " +
        					action.getId());
        			out.newLine();
        		}
        	}
        	
        	en = predicates.breadthFirstEnumeration();
        	while(en.hasMoreElements())
        	{
        		// write line of the form "#define PROJECT_ACTION_name id"
        		DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
        		Object userObj = tnode.getUserObject();
        		if (userObj instanceof SB_Predicate)
        		{
        			SB_Predicate predicate = (SB_Predicate)userObj;
        			out.write("#define " + nameCAPS + "_PRED_" + predicate.getName() + " " +
        					predicate.getId());
        			out.newLine();
        		}
        	}
		}
		
		if (userDefined)
		{
			// CONSTANTS
			out.write("\n// constants");
			out.newLine();
			
			// doesn't exist!!!
			DefaultMutableTreeNode constants = mEditorApp.getCatalog()._constants;
			// constants->Sort() -- already sorted since they are in a tree, right???
			
			Enumeration en = constants.breadthFirstEnumeration();
			while(en.hasMoreElements())
			{
				DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
				Object userObj = tnode.getUserObject();
				if (userObj instanceof SB_Constant)
				{
					SB_Constant constant = (SB_Constant)userObj;
					if (constant.getType() == SB_VarType.kVector.getState())
					{
						// can't generate code for vector constants in c++
						continue;
					}
					
					String descript = "";	// constant->GetDescript()
					if (!descript.isEmpty())
					{
						out.write("// " + descript);
						out.newLine();
					}
					
					out.write("#define " + nameCAPS + "_" + constant.getName() + " " + 
							constant.getValue());
					out.newLine();
				}
			}
			
			DefaultMutableTreeNode userTypes = mEditorApp.getCatalog()._types;
			en = userTypes.breadthFirstEnumeration();
			while(en.hasMoreElements())
			{
				DefaultMutableTreeNode tnode = (DefaultMutableTreeNode)en.nextElement();
				Object userObj = tnode.getUserObject();
				
				// ignore SB_Package
				if (userObj instanceof SB_Class)
				{
					// TODO: is enum???
					SB_Class sbclass = (SB_Class)userObj;
					
					// on your own for now
				}
			}
		}
	}
	
	protected void exportCPPConstants(String filename,
			DefaultMutableTreeNode actions, DefaultMutableTreeNode predicates,
			boolean constants, boolean userDefined,
			boolean openAfterExport, String name) throws IOException
	{
		System.out.println("exporting CPP constants is not currently supported");
	}
	
	protected static String[] wrapText(String text, int len)
	{
		// return empty array for null text
		if (text == null)
			return new String[] {};

		// return text if len is zero or less
		if (len <= 0)
			return new String[] { text };

		// return text if less than length
		if (text.length() <= len)
			return new String[] { text };

		char[] chars = text.toCharArray();
		ArrayList lines = new ArrayList();
		StringBuffer line = new StringBuffer();
		StringBuffer word = new StringBuffer();

		for (int i = 0; i < chars.length; i++)
		{
			word.append(chars[i]);

			if (chars[i] == ' ')
			{
				if ((line.length() + word.length()) > len)
				{
					lines.add(line.toString());
					line.delete(0, line.length());
				}

				line.append(word);
				word.delete(0, word.length());
			}
		}

		// handle any extra chars in current word
		if (word.length() > 0)
		{
			if ((line.length() + word.length()) > len)
			{
				lines.add(line.toString());
				line.delete(0, line.length());
			}
			line.append(word);
		}

		// handle extra line
		if (line.length() > 0)
		{
			lines.add(line.toString());
		}

		String[] ret = new String[lines.size()];
		int c = 0; // counter
		//for (Enumeration e = lines.elements(); e.hasMoreElements(); c++)
		for(Object oline : lines)
		{
			ret[c] = (String) oline;
		}

		return ret;
	}
	
	protected void exportClass()
	{
		if (mSBPFile != null)
		{
//			String name = mSBPFile.getName();
//			name = name.substring(0, name.length() - 4);
//			fileJava = new File(_fileSBP.getParent() + /* File.separator */"//"
//					+ name + ".java");
		}
		JFileChooser chooser = this.getFileChooserJava();
		chooser.setDialogTitle("Export Java Class");
		int returnVal = chooser.showDialog(ComponentRegistry.getFrame(), "Export");
		if(returnVal == JFileChooser.APPROVE_OPTION)
		{
			mJavaFile = chooser.getSelectedFile();
			String ext = Util.getFileExtension(mJavaFile);
			if(ext == null || !ext.equals("java")) mJavaFile = new File(mJavaFile.getPath() + ".java");
			if(mJavaFile.exists())
			{
				int n = JOptionPane.showConfirmDialog(ComponentRegistry.getFrame(), "'"
						+ mJavaFile.getName() + "' already exists.   \n"
						+ "Do you want to replace it?", "Export Java Class",
						JOptionPane.YES_NO_OPTION);
				if(n == JOptionPane.NO_OPTION) return;
			}

			try
			{
				// open XML file for writing
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mJavaFile)));

				// write comment line
				String name = mJavaFile.getName();
				out.write("// " + name + " : SimBionic generated constants");
				out.newLine();
				out.newLine();
				name = name.substring(0, name.length() - 5);
				out.write("public class " + name);
				out.newLine();
				out.write("{");
				out.newLine();
				
				// SIM revision number
				int rev = this.getRevisionNumber(mSimFile);
				if (rev == 0) rev = 1;
				out.write("// sim revision number");
				out.newLine();
				out.write("\tpublic static final int SIM_REV = " + rev + ";");
				out.newLine();
				out.newLine();

				// export actions, predicates
				mEditorApp.getCatalog().exportClass(out, name);

				out.write("}");
				out.newLine();

				out.close();
			}
			catch (IOException exception)
			{
				System.err.println("i/o exception");
			}
		}
	}

  protected void importXML()
	{
		//		if (saveModified() == JOptionPane.CANCEL_OPTION)
		//			return;

		JFileChooser chooser = this.getFileChooserXML();
		chooser.setDialogTitle("Import XML");
		int returnVal = chooser.showDialog(ComponentRegistry.getFrame(), "Import");
		if (returnVal == JFileChooser.APPROVE_OPTION)
		{
			mXMLFile = chooser.getSelectedFile();
			String ext = Util.getFileExtension(mXMLFile);
			if(ext == null || !ext.equals("xml")) mXMLFile = new File(mXMLFile.getPath() + ".xml");
			if(!mXMLFile.exists())
			{
				JOptionPane.showMessageDialog(ComponentRegistry.getFrame(), "'"
						+ mXMLFile.getPath() + "' cannot be found.   ", "File Not Found",
						JOptionPane.WARNING_MESSAGE);
				return;
			}

			mSBPFile = null;
			mAPDFile = null;
			mSimFile = null;
			
      
      // Use an instance of ourselves as the SAX event handler
      DefaultHandler handler = new SimBionicXMLHandler(mEditorApp);
      // Use the default (non-validating) parser
      SAXParserFactory factory = SAXParserFactory.newInstance();
      try 
			{
          // Parse the input
          SAXParser saxParser = factory.newSAXParser();
          saxParser.parse(mXMLFile, handler);

      } 
//			try
//			{
//				XMLReader _xr;
//				if (_xr == null) _xr = XMLReaderFactory.createXMLReader();//new
//				// org.apache.crimson.parser.XMLReaderImpl();
//				SimBionicXMLHandler handler = new SimBionicXMLHandler();
//				_xr.setContentHandler(handler);
//				_xr.setErrorHandler(handler);
//				FileReader editorReader = new FileReader(fileXML);
//				try
//				{
//					_xr.parse(new InputSource(editorReader));
//				}
//				catch (SAXException exception)
//				{
//					System.err.println("SAX exception: " + exception.getMessage());
//				}
//				editorReader.close();
//			}
			catch (FileNotFoundException exception)
			{
				exception.printStackTrace();
				System.err.println("file not found: " + mXMLFile.getPath());
			}
			catch (IOException exception)
			{
				exception.printStackTrace();
				System.err.println("i/o exception: " + mXMLFile.getPath());
			}
			catch (SAXException exception)
			{
				exception.printStackTrace();
			}
			catch (ParserConfigurationException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			SB_Catalog _catalog = mEditorApp.getCatalog();
			
			DefaultMutableTreeNode treeNode = _catalog.findNodeByName("Core Actions",	_catalog._actions);
            if (treeNode != null)
            {
    			SB_Folder folder = (SB_Folder) treeNode.getUserObject();
    			folder.setEditable(false);
            }
			treeNode = _catalog.findNodeByName("Core Predicates",
					_catalog._predicates);
			if (treeNode != null)
            {
                SB_Folder folder = (SB_Folder) treeNode.getUserObject();
                folder.setEditable(false);
            }

			//SB_ToolBar toolBar = ComponentRegistry.getToolBar();
			//toolBar.clearStacks();

//			setAPDModified(true);
//			setSBPModified(true);
//			_catalog.setBTNModified(true);
//			
//			mEditorApp.saveAction.setEnabled(true);
//
//			_catalog.updateComboBehav();
//			SB_TabbedCanvas tabbedCanvas = (SB_TabbedCanvas) ComponentRegistry.getContent();
//			tabbedCanvas._behavior = null;
//			tabbedCanvas.setBehavior(_catalog._main, false);
		}
	}

	protected void exportXML()
	{
		File fileXML = null;
		if (mSBPFile != null)
		{
			String name = mSBPFile.getName();
			name = name.substring(0, name.length() - 4);
			fileXML = new File(mSBPFile.getParent() + File.separator + name + ".xml");
		}
		JFileChooser chooser = this.getFileChooserXML();
		getFileChooserXML().setDialogTitle("Export XML");
		int returnVal = chooser.showDialog(ComponentRegistry.getFrame(), "Export");
		if (returnVal == JFileChooser.APPROVE_OPTION)
		{
			fileXML = chooser.getSelectedFile();
			String ext = Util.getFileExtension(fileXML);
			if (ext == null) fileXML = new File(fileXML.getPath() + ".xml");
			if (fileXML.exists())
			{
				int n = JOptionPane.showConfirmDialog(ComponentRegistry.getFrame(), "'"
						+ fileXML.getPath() + "' already exists.   \n"
						+ "Do you want to replace it?", "Export XML",
						JOptionPane.YES_NO_OPTION);
				if (n == JOptionPane.NO_OPTION) return;
			}

			try
			{
				// open XML file for writing
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
						new FileOutputStream(fileXML)));

				out.write("<project>");
				out.newLine();

				// export actions, predicates, constants, descriptors
				out.write("\t<apd>");
				out.newLine();
				SB_ProjectBar project = ComponentRegistry.getProjectBar();
				project._catalog.exportXML_APD(out);
				project._descriptors.exportXML_APD(out);
				out.write("\t</apd>");
				out.newLine();

				// export behaviors, globals
				project._catalog.exportXML_SBP(out);
				project._catalog.exportXML_BTNs(out);

				out.write("</project>");
				out.newLine();

				out.close();
			}
			catch (IOException exception)
			{
				System.err.println("i/o exception");
			}
		}
	}

	
	
	public JFileChooser getFileChooserXML()
	{
		if(mXMLFile == null) mXMLFile = new File(System.getProperty("user.dir"));
		JFileChooser chooser = new JFileChooser(mXMLFile);
		chooser.setFileFilter(Util.createFileFilterForExt("xml", "XML Files (*.xml)", true));
		chooser.setAcceptAllFileFilterUsed(false);

		return chooser;
	}

	public JFileChooser getFileChooserH()
	{
		if(mHeaderFile == null) mHeaderFile = new File(System.getProperty("user.dir"));
		JFileChooser chooser = new JFileChooser(new File(System.getProperty("user.dir")));
		chooser.setFileFilter(Util.createFileFilterForExt("h", "C++ Header Files (*.h)", true));
		chooser.setAcceptAllFileFilterUsed(false);

		return chooser;
	}

	
	public JFileChooser getFileChooserJava()
	{
		if(mJavaFile == null) mJavaFile = new File(System.getProperty("user.dir"));
		JFileChooser chooser = new JFileChooser(new File(System.getProperty("user.dir")));
		chooser.setFileFilter(Util.createFileFilterForExt("java", "Java Files (*.java)", true));
		chooser.setAcceptAllFileFilterUsed(false);

		return chooser;
	}
	
	public JFileChooser getFileChooserDir()
	{
		JFileChooser chooser = new JFileChooser(new File(System.getProperty("user.dir")));
		
		return chooser;
	}

	/**
	 * @return Returns the simFile.
	 */
	public File getSimFile()
	{
		return this.mSimFile;
	}
	
	/**
	 * @param pSimFile The simFile to set.
	 */
	public void setSimFile(String pSimFileName)
	{
		this.mSimFile = new File(pSimFileName);
	}
	
	/**
	 * @param pSimFile The simFile to set.
	 */
	public void setSimFile(File pSimFile)
	{
		this.mSimFile = pSimFile;
	}
	
	public static String convertTypeToSBType(int typeNum)
	{
		SB_VarType newType = SB_TypeManager.convertOldTypeId(typeNum);
		switch(newType.getState())
		{
			case -1: return "AI_Invalid";
		      case 0: return "AI_Float";
		      case 1: return "AI_String";
		      case 2: return "AI_Entity";
		      case 3: return "AI_Vector";
		      case 4: return "AI_Data";
		      case 5: return "Object";
		      case 6: return "AI_Integer";
		      case 7: return "AI_Boolean";
		      case 8: return "AI_Array";
		      case 9: return "Object";
		      case 10: return "Object";
		}
		
		return "Object";
	}
	
	protected String getCPPTypeName(SB_Parameter param, boolean checkDirection)
	{
		SB_ProjectBar pbar = mEditorApp.getProjectBar();
		SB_VarType newType = SB_TypeManager.convertOldTypeId(param.getType());
		int index = newType.getState();
		
		String typeName;
		if (index >= 128)
		{
			assert(false);
			// TODO: convert this code
			SB_Catalog catalog = pbar.getCatalog();
			//CEnumType *enumType = catalog->FindEnumType(index);
			//if (enumType)
			//{
			//	if (enumType->IsIntegerType())
			//		index = kInteger;
			//	else
			//		index = kString;
			//}
			
			typeName = "Unknown";
		}
		else
		{
			typeName =  Character.toUpperCase(param.getTypeName().charAt(0)) + param.getTypeName().substring(1);
		}
		
		if ((index == SB_VarType.kAny.getState() ||
			 index == SB_VarType.kArray.getState() ||
			 index == SB_VarType.kTable.getState()))
		{
			if (checkDirection)
				typeName = "Param";
			else
				typeName = "";
		}
		
		if (checkDirection)
		{
			int direction = param.getDirection();
			if (direction != DIRECTION.IN_DIR.ordinal() && index == SB_VarType.kString.getState())
				typeName = "std::string&";
			else
			{
				typeName = "AI_" + typeName;
				if (direction != DIRECTION.IN_DIR.ordinal())
					typeName += "&";
			}
		}
		else
		{
			if ((index != SB_VarType.kAny.getState() &&
				 index != SB_VarType.kArray.getState() &&
				 index != SB_VarType.kTable.getState()))
			{
				typeName = "." + typeName + "()";
			}
		}
		
		return typeName;
	}
}